#pragma once
#include "Binding/BoundGlobalScope.hpp"

#include "Binding/BoundBlock.hpp"
#include "EvaluationResult.hpp"
#include "Lowering/Lowerer.hpp"
#include "Syntax/Tree.hpp"
#include "Symbols/VariableMap.hpp"

#include <shared_mutex>
class Compilation
{
public:
    SharedTree             mSyntaxTree;
    Compilation           *Previous;
    SharedBoundGlobalScope _globalScope;

public:
    static std::shared_mutex sharedMutex;

public:
    Compilation(SharedTree syntaxTree) : Compilation(nullptr, syntaxTree) {}
    Compilation(Compilation *previous, SharedTree syntaxTree) : Previous(previous), mSyntaxTree(syntaxTree), _globalScope(nullptr) {}

    SharedBoundGlobalScope GlobalScope();

    Compilation     *ContinueWith(SharedTree syntaxTree) { return new Compilation(this, syntaxTree); }
    EvaluationResult Evaluate(SharedVariableMap variable);

    void EmitTree(std::stringstream &writer) { GetStatement()->WriteTo(writer); }

private:
    SharedBoundBlockStatement GetStatement()
    {
        auto result = this->GlobalScope()->Statement;
        return Lowerer::Lower(result);
    }
};